package com.inspur.edp.formserver.vmmanager;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.collection.GspAssociationCollection;
import com.inspur.edp.cef.designtime.api.collection.GspFieldCollection;
import com.inspur.edp.cef.designtime.api.element.GspAssociation;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.IGspCommonModel;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.formserver.viewmodel.GspViewModel;
import com.inspur.edp.formserver.viewmodel.GspViewModelElement;
import com.inspur.edp.formserver.viewmodel.GspViewObject;
import com.inspur.edp.formserver.viewmodel.collection.VMElementCollection;
import com.inspur.edp.formserver.viewmodel.collection.ViewObjectCollection;
import com.inspur.edp.formserver.viewmodel.json.model.ViewModelDeserializer;
import com.inspur.edp.formserver.viewmodel.json.model.ViewModelSerializer;
import com.inspur.edp.formserver.vmmanager.exception.VmManagerException;
import com.inspur.edp.lcm.metadata.api.IMetadataContent;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.RefCommonService;
import com.inspur.edp.lcm.metadata.spi.MetadataTransferSerializer;
import com.inspur.edp.web.help.metadata.HelpMetadataContent;
import io.iec.edp.caf.commons.exception.ExceptionLevel;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

public class TransferSerializer implements MetadataTransferSerializer {


    //region getMapper

    private ObjectMapper getMapper() {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(IGspCommonModel.class, new ViewModelDeserializer());
        module.addSerializer(IGspCommonModel.class, new ViewModelSerializer());
        mapper.registerModule(module);
        return mapper;
    }

    //endregion

    //region 序列化
    public final String serialize(IMetadataContent metadataContent) {
        GspViewModel viewModel = (GspViewModel) ((metadataContent instanceof GspViewModel) ? metadataContent : null);
//        dealContent(viewModel);
        String modelJson = null;
        try {
            modelJson = getMapper().writeValueAsString(viewModel);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("ViewModel序列化失败！");
        }
        return modelJson;
    }

    private void dealContent(GspViewModel viewModel) {
        dealObject(viewModel.getMainObject());
    }

    private void dealObject(GspViewObject viewObject){

        ViewObjectCollection childObjs = viewObject.getContainChildObjects();
        if(childObjs != null && childObjs.size() > 0){
            childObjs.forEach((childObj) -> {
                dealObject((GspViewObject)childObj);
            });
        }

        VMElementCollection eles = viewObject.getContainElements();
        if(eles != null && eles.size() > 0){
            eles.forEach((ele) -> {
                dealElement(ele);
            });
        }
    }

    private void dealElement(IGspCommonField element){
        if(element.getObjectType() != GspElementObjectType.Association)
            return;

        GspAssociationCollection assos = element.getChildAssociations();
        if(assos != null && assos.size() > 0){
            assos.forEach((asso) -> {
                dealAssociation(asso);
            });
        }
    }

    private void dealAssociation(GspAssociation association){

        GspFieldCollection refEles = association.getRefElementCollection();
        if(refEles != null && refEles.size() > 0){
            refEles.forEach((refEle) -> {
                dealRefElement(association, refEle);
            });
        }
    }

    private void dealRefElement(GspAssociation association, IGspCommonField refElement){
        if(refElement.getObjectType() != GspElementObjectType.Association)
            return ;
        RefCommonService service= SpringBeanUtils.getBean(RefCommonService.class);
        GspMetadata refMetadata = service.getRefMetadata(association.getRefModelID());
        if(refMetadata == null)
            throw new VmManagerException("","", "关联be["+association.getRefModelID()+"] ["+association.getRefModelCode()+"]没有获取到。",null, ExceptionLevel.Error,false);
        GspBusinessEntity refBe= (GspBusinessEntity) refMetadata.getContent();
          IGspCommonObject refObj = refBe.findObjectById(association.getRefObjectID());
        if(refObj == null)
            throw new VmManagerException("","", "关联be["+association.getRefModelCode()+"]中没有获取到节点["+association.getRefObjectID()+"] ["+association.getRefObjectCode()+"]。",null, ExceptionLevel.Error,false);

        IGspCommonElement element = refObj.findElement(refElement.getRefElementId());
        if(element == null)
            throw new VmManagerException("","", "关联be["+association.getRefModelCode()+"]中没有获取到字段["+refElement.getRefElementId()+"] ["+refElement.getLabelID()+"]。",null, ExceptionLevel.Error,false);

        refElement.getChildAssociations().addAll(element.getChildAssociations().clone());

        dealElement(refElement);
    }
    //endregion


    public final IMetadataContent deserialize(String contentString) {
        GspViewModel viewModel = new GspViewModel();
        try {
            viewModel = getMapper().readValue(contentString, GspViewModel.class);
        } catch (JsonProcessingException e) {
            throw new VmManagerException("","", "vo反序列化失败" + contentString ,null, ExceptionLevel.Error,false);

        }
        return viewModel;
    }
}
